
#include "core/core_message.h"
#include "core/service.h"

extern "C" {

static bool check_msg_type(MsgType type) {
  switch (type) {
    case kLogic:
    case kTimer:
      return true;
  }
  return false;
}

// data_info format:
// 0 ~ 15 bits : message length
// 16 ~ 23 bits : no use
// 24 ~ 30 bits : type
// 31 bit : is_owner
static uint32_t build_data_info(bool is_owner, MsgType type, uint16_t len) {
  uint32_t is_owner32 = is_owner ? (1 << 31) : 0;
  return is_owner32 | ((uint32_t)type << 24) | (uint32_t)len;
}

bool create_message(void* source_service, 
                    uint32_t session,
                    bool is_owner,
                    MsgType type,
                    const char* data,
                    uint16_t len,
                    CoreMessage* msg) {
  if (!data || !msg || !check_msg_type(type)) return false;
  Service* source = (Service*)source_service;
  (*msg).source_handle = source ? source->handle().value() : -1;
  (*msg).session = (session == -1 && source) ? source->AllocSession() : session;
  (*msg).data = data;
  (*msg).data_info = build_data_info(is_owner, type, len);
  return true;
}

bool message_is_owner(const CoreMessage* message) {
  return message ? (message->data_info & 0x80000000) : false;
}

uint8_t message_type(const CoreMessage* message) {
  if (message)
    return (message->data_info & 0x7f000000) >> 24;
  return -1;
}

uint16_t message_length(const CoreMessage* message) {
  return message ? (message->data_info & 0xffff) : 0;
}

}

